/**
 * 创建中转数据结构
 * 
 * 模块导出规范遵循 CommonJS
 * 
 */
module.exports = {
  createStatementData: function (invoice, plays) {
    const result = {};

    // 顾客信息
    result.customer = invoice.customer;
    // 剧目信息：通过 map 函数遍历 performances，将其属性进行扩展
    result.performances = invoice.performances.map(enrichPerformance);
    // 总费用
    result.totalAmount = totalAmount(result);
    // 总积分
    result.totalVolumeCredits = totalVolumeCredits(result);
    return result;

    /**
     * 计算总费用
     */
    function totalAmount(data) {
      return data.performances
        .reduce((total, p) => total + p.amount, 0);
    }

    /**
     * 计算观众量积分总和
     */
    function totalVolumeCredits(data) {
      return data.performances
        .reduce((total, p) => total + p.volumeCredits, 0);
    }

    /**
    * 根据账单中的数据获取对应剧目信息
    * @param {*} aPerformance 
    * @returns 
    */
    function playFor(aPerformance) {
      return plays[aPerformance.playID];
    }


    /**
     * 将其中每一个 aPerformance 的属性由【playID,audience】 扩展为【playID,audience，play(name,type)】
     * @returns 新增了额外属性的 Performance 对象
     */
    function enrichPerformance(aPerformance) {

      const calculator = createPerformanceCalculator(aPerformance, playFor(aPerformance));

      const result = Object.assign({}, aPerformance);
      result.play = calculator.play;
      result.amount = calculator.amount;
      result.volumeCredits = calculator.volumeCredits;
      return result;
    }


  }
}

/**
 * 工厂函数: 根据剧目类型（aPlay.type）返回不同的子类,每个子类对费用、积分的计算逻辑不同
 * @param {*} aPerformance 
 * @param {*} aPlay 
 * @returns 
 */
function createPerformanceCalculator(aPerformance, aPlay) {
  switch (aPlay.type) {
    case "tragedy": return new TragedyCaculator(aPerformance, aPlay);
    case "comedy": return new ComedyCaculator(aPerformance, aPlay);
  }
  return new PerformanceCalculator(aPerformance, aPlay);

}

/**
 * 超类：计算演出数据（费用、观众积分）
 */
class PerformanceCalculator {
  constructor(aPerformance, aPlay) {
    this.performance = aPerformance;
    this.play = aPlay;
  }
  // 计算单场剧目的费用
  get amount() {
    throw new Error(`subclass responsibility`);
  }

  // 计算单场剧目产生的观众量积分
  get volumeCredits() {
    return Math.max(this.performance.audience - 30, 0);
  }

}


/**
 * 悲剧类
 */
class TragedyCaculator extends PerformanceCalculator {

  // 计算费用
  get amount() {
    let result = 40000;
    if (this.performance.audience > 30) {
      result += 1000 * (this.performance.audience - 30);
    }
    return result;
  }
}

/**
 * 喜剧类
 */
class ComedyCaculator extends PerformanceCalculator {
  // 计算费用
  get amount() {
    let result = 30000;
    if (this.performance.audience > 20) {
      result += 10000 + 500 * (this.performance.audience - 20);
    }
    result += 300 * this.performance.audience;
    return result;
  }
  // 计算积分: 喜剧的积分计算比较特殊，需要重写父类的方法
  get volumeCredits() {
    return super.volumeCredits + Math.floor(this.performance.audience / 5);

  }
}

